﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using QFlow.Data;
using Microsoft.Reporting.WinForms;

namespace QFlow.Reports
{
    public partial class InventoryReportViewer : Utils.BaseForm
    {
        public InventoryReportViewer(QFlowDbContext context)
            : base(context)
        {
            InitializeComponent();
        }

        private void InventoryReportViewer_Load(object sender, EventArgs e)
        {
            cmbBrands.DataSource = this.Context.ProductBrands.ToArray();
            cmbCategories.DataSource = this.Context.ProductCategories.ToArray();
            cmbBrands.SelectedIndex = -1;
            cmbCategories.SelectedIndex = -1;
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            int receivedItemTypeId = this.Context.ItemTypes.GetReceivedType().ItemTypeID;
            int closedStatusId = this.Context.OrderStatus.GetClosedStatus().StatusID;

            int brandId = 0, categoryId = 0;

            if (cmbBrands.SelectedIndex != -1)
                brandId = (int)cmbBrands.SelectedValue;
            if (cmbCategories.SelectedIndex != -1)
                categoryId = (int)cmbCategories.SelectedValue;

            DateTime fromDate = dtFrom.Value.Date;
            DateTime toDate = dtTo.Value.Date;

            var purchased = from product in this.Context.StockableProducts
                            join pItem in this.Context.PurchaseItems
                            on product.ProductID equals pItem.ProductID

                            where
                            (brandId == 0 ? true : product.Product.BrandID == brandId)
                            &&
                            (categoryId == 0 ? true : product.Product.CategoryID == categoryId)
                            &&
                            pItem.PurchaseOrder.Date.Date >= fromDate
                            &&
                            pItem.PurchaseOrder.Date.Date <= toDate
                            &&
                            pItem.PurchaseOrder.StatusID == closedStatusId
                            &&
                            pItem.ItemTypeID == receivedItemTypeId

                            group pItem by pItem.ProductID into g

                            select new
                            {
                                PId = g.Key,
                                Purchased = g.Sum(item => item.Quantity)
                            };

            var sold = from product in this.Context.StockableProducts
                       join sItem in this.Context.SaleItems
                       on product.ProductID equals sItem.ProductID

                       where
                       (brandId == 0 ? true : product.Product.BrandID == brandId)
                       &&
                       (categoryId == 0 ? true : product.Product.CategoryID == categoryId)
                       &&
                       sItem.SaleOrder.Date.Date >= fromDate
                       &&
                       sItem.SaleOrder.Date.Date <= toDate
                       &&
                       sItem.SaleOrder.StatusID == closedStatusId
                       &&
                       sItem.ItemTypeID == receivedItemTypeId

                       group sItem by sItem.ProductID into g

                       select new
                       {
                           PId = g.Key,
                           Sold = g.Sum(item => item.Quantity)
                       };

            var result = from product in this.Context.StockableProducts
                         join purchase in purchased
                         on product.ProductID equals purchase.PId
                         into temp
                         from t in temp.DefaultIfEmpty()
                         join sales in sold
                         on product.ProductID equals sales.PId
                         into temp2
                         from t2 in temp2.DefaultIfEmpty()
                         where
                         (brandId == 0 ? true : product.Product.BrandID == brandId)
                         &&
                         (categoryId == 0 ? true : product.Product.CategoryID == categoryId)
                         select new InventoryReportResult
                         {
                             ProductName = product.Product.Name,
                             GlobalBarcode = product.GlobalBarcode,
                             CurrentQuantity = product.CurrentQuantity,
                             Purchased = (t == null ? 0 : t.Purchased),
                             Sold = (t2 == null ? 0 : t2.Sold)
                         };

            InventoryReportResultBindingSource.DataSource = result.ToArray();
            ReportParameterInfoCollection collection = reportViewer1.LocalReport.GetParameters();

            List<Microsoft.Reporting.WinForms.ReportParameter> repeortParams = new List<Microsoft.Reporting.WinForms.ReportParameter>();
            repeortParams.Add(new Microsoft.Reporting.WinForms.ReportParameter("FromDate", fromDate.ToString("dd-MM-yyyy")));
            repeortParams.Add(new Microsoft.Reporting.WinForms.ReportParameter("ToDate", toDate.ToString("dd-MM-yyyy")));
            repeortParams.Add(new Microsoft.Reporting.WinForms.ReportParameter("Brand", (brandId != 0 ? cmbBrands.Text : "All")));
            repeortParams.Add(new Microsoft.Reporting.WinForms.ReportParameter("Category", (categoryId != 0 ? cmbCategories.Text : "All")));

            reportViewer1.LocalReport.SetParameters(repeortParams);
            reportViewer1.RefreshReport();
        }
    }


    public class InventoryReportResult
    {
        public string ProductName { get; set; }
        public string GlobalBarcode { get; set; }
        public double CurrentQuantity { get; set; }
        public double Purchased { get; set; }
        public double Sold { get; set; }
    }
}
